package archer.back.controllers

import java.util.Date

import archer.back.models.{ CrawlResultModel, DetailCrawlPlan }
import archer.back.utils.PoiStyles
import models.TableData

import scala.concurrent.{ ExecutionContext, Future }
import cats.implicits._
import io.circe.syntax._
import io.circe.generic.auto._
import utils._
import net.scalax.cpoi.api._
import org.apache.poi.hssf.usermodel.HSSFWorkbook
import org.apache.poi.ss.usermodel.Workbook

class CrawlResultService(commonDB: CommonDB, elasticService: ElasticService)(
  implicit
  ec: ExecutionContext)
  extends ArcherHelper {

  import models.CrawlTables._
  import profile.api._

  def list(page: Int, limit: Int): Future[TableData[Seq[DetailCrawlPlan]]] = {
    val resultF = futureLess.lift {
      val action = CommonResult.commonResult(
        UpdateCrawlPlan,
        UpdateCrawlPlan.sortBy(_.modifiedTime.desc),
        SlickParam.empty.pageIndex(page - 1).pageSize(limit))

      val (list, count) = futureLess.unlift(commonDB.db.run(action))

      val actions = futureLess.unlift(
        commonDB.db.run(
          UpdateCrawlAction
            .filter(s => s.planId inSetBind list.map(_.id))
            .result))

      val result = list.map { each =>
        val currActions = actions.filter(a => a.planId === each.id)
        DetailCrawlPlan(
          id = each.id,
          name = each.name,
          parentNodeId = each.parentNodeId,
          modifiedTime = each.modifiedTime,
          sum = currActions.size,
          failed = currActions
            .filter(a =>
              (a.isSuccessed === Option(false)) && (a.retryTimes > 3))
            .size,
          success = currActions
            .filter(a => (a.isSuccessed === Option(true)))
            .size,
          running = currActions
            .filter(a =>
              (((a.isSuccessed === Option(false)) && (a.retryTimes <= 3)) || a.isSuccessed.isEmpty))
            .size)
      }

      TableData(data = result, count = Option(count))
    }
    resultF
  }

  def planToExce(planId: Int): Future[Workbook] = {
    import writers._

    val date = new Date()
    commonDB.db
      .run(UpdateCrawlAction.filter(_.planId === planId).to[List].result)
      .flatMap { actions =>
        commonDB.db
          .run(UpdateTreeNode.to[List].result)
          .map { nodes =>
            CrawlResultModel.total.map(
              name =>
                CPoi
                  .wrapData(name)
                  .addTransform(PoiStyles.TextFormat())
                  .untyped) +:
              actions.map(a =>
                new CrawlResultModel(a, nodes, date)
                  .lineList(CrawlResultModel.total))
          }
      }
      .map { list =>
        val workbook = new HSSFWorkbook()
        val sheet = workbook.createSheet("抓取结果")
        val cellList = list.zipWithIndex.map {
          case (item, index) =>
            val row = sheet.createRow(index)
            item.zipWithIndex.map {
              case (cellData, index) => row.createCell(index) -> cellData
            }
        }.flatten
        CPoi.multiplySet(CPoi.newStyleGen, cellList)
        workbook
      }
  }

}
